#include "stdafx.h"
#include "WmiInfo.h"


CWmiInfo::CWmiInfo(void)
{
}


CWmiInfo::~CWmiInfo(void)
{
	Cleanup();
}



BOOL CWmiInfo::Init()
{

	HRESULT hres;
	hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED );

	if (FAILED(hres))
	{
		::MessageBox(NULL, _T("Can't Initialize COM"), NULL,NULL);
		return TRUE;
	}

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

	if (FAILED(hres) && hres != RPC_E_TOO_LATE)
	{
		CoUninitialize();
		return FALSE;
	}



    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    //IWbemLocator *pLoc = NULL;
	pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {

        CoUninitialize();
        return FALSE;                // Program has failed.
    }

    //IWbemServices *pSvc = NULL;
	pSvc = NULL;

    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
        _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
        NULL,                    // User name. NULL = current user
        NULL,                    // User password. NULL = current
        0,                       // Locale. NULL indicates current
        NULL,                    // Security flags.
        0,                       // Authority (e.g. Kerberos)
        0,                       // Context object 
        &pSvc                    // pointer to IWbemServices proxy
        );

    if (FAILED(hres))
    {

        pLoc->Release();     
        CoUninitialize();
		return FALSE;                // Program has failed.
    }

    //cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels on the proxy -------------------------

    hres = CoSetProxyBlanket(
        pSvc,                        // Indicates the proxy to set
        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
        NULL,                        // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL,                        // client identity
        EOAC_NONE                    // proxy capabilities 
        );

    if (FAILED(hres))
    {

        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return FALSE;               // Program has failed.
    }

	return TRUE;
}



BOOL CWmiInfo::GetInfo(CString szQuery, CString szName, CStringArray& szInfo)
{

		if (!Init())
	{
		return FALSE;
	}

	HRESULT hres = NULL;

	CString strQuery = _T("SELECT * FROM ") + szQuery;
	
	IEnumWbemClassObject* pEnumerator = NULL;
	
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t(strQuery),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);

    if (FAILED(hres))
    {
        //cout << "Query for operating system name failed."
        //    << " Error code = 0x" 
        //    << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------

    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        _variant_t vtProp;

        // Get the value of the Name property
        hr = pclsObj->Get(szName, 0, &vtProp, 0, 0);
		BSTR boj;
		pclsObj->GetObjectText(0 ,&boj);

		if ((vtProp.vt != VT_EMPTY) && (vtProp.vt != VT_NULL))
		{
			szInfo.Add(vtProp.bstrVal);
		}

    }

	// Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();

	return TRUE;
}



BOOL CWmiInfo::GetInfo(CString szQuery, CStringArray& szProperty, CStringArray& szInfo)
{

	if (!Init())
	{
		return FALSE;
	}

	HRESULT hres = NULL;
	
	CString strQuery = _T("SELECT * FROM ") + szQuery;
	
	IEnumWbemClassObject* pEnumerator = NULL;
	
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t(strQuery),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);

    if (FAILED(hres))
    {
        //cout << "Query for operating system name failed."
        //    << " Error code = 0x" 
        //    << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------

    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        _variant_t vtProp;

		SAFEARRAY *pvNames = NULL;
		pclsObj->GetNames(NULL, WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN, NULL ,&pvNames);

		long vbl, vbu;
		SafeArrayGetLBound(pvNames, 1, &vbl);
		SafeArrayGetUBound(pvNames, 1, &vbu);
		for(long idx=vbl; idx <= vbu; idx++)
		{
			long aidx = idx;
			WCHAR *wsName = 0;
			_variant_t vtProp;
                      
			SafeArrayGetElement(pvNames, &aidx, &wsName);

			BSTR bs = SysAllocString(wsName);
			HRESULT hRes = pclsObj->Get(bs, 0, &vtProp, NULL, 0);
			szProperty.Add(bs);
			SysFreeString(bs);

			BSTR boj;
			pclsObj->GetObjectText(0 ,&boj);
			CString str;

			if ((vtProp.vt != VT_EMPTY) && (vtProp.vt != VT_NULL && vtProp.vt != VT_ERROR))
			{
				switch(vtProp.vt)
				{

				case VT_BSTR:         //var is BSTR type
					 str = vtProp.bstrVal;
					 break;

				case VT_I2:           //var is short int type
					 str.Format(_T("%d"),(int)vtProp.iVal);
					 break;

				case VT_I4:          //var is long int type
					 str.Format(_T("%d"),vtProp.lVal);
					 break;

				case VT_R4:         //var is float type
					 str.Format(_T("%10.6f"),(double)vtProp.fltVal);
					 break;

				case VT_R8:         //var is double type
					 str.Format(_T("%10.6f"),vtProp.dblVal);
					 break;

				case VT_CY:        //var is CY type
					 str = COleCurrency(vtProp).Format();
					 break;

				case VT_DATE:     //var is DATE type
					 str = COleDateTime(vtProp).Format();
					 break;

				case VT_BOOL:     //var is  VARIANT_BOOL
					 str = (vtProp.boolVal==0) ?_T("FALSE"): _T("TRUE");
					 break;
				case VT_UI1:
					str.Format(_T("None"));
					break;

				default:
					 str.Format(_T("Unk type %d\n"),vtProp.vt);
					 TRACE(_T("Unknown type %d\n"),vtProp.vt);
				}
				szInfo.Add(str);

			}

		}

			if(pvNames)
			{
				SafeArrayDestroy(pvNames);
			}
	
	}

	// Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    if (pclsObj)
	{
		pclsObj->Release();
	}
    

	return TRUE;
}

void CWmiInfo::Cleanup()
{

	CoUninitialize();
	
}